#include "BEEP_LED_module/BEEP_LED.hpp"

#ifdef DBG_TAG
#undef DBG_TAG
#endif
#ifdef DBG_LVL
#undef DBG_LVL
#endif

#define DBG_TAG     "beep_led"
#define DBG_LVL     DBG_LOG

extern "C"
{
#include <rtdbg.h>
}

using namespace std;

/******************************************************************************
 *
 * @brief:     BEEP类实现
 *
 ******************************************************************************/
BEEP_LED::BEEP_LED(rt_base_t pin_num, beep_led_active_mode mode, beep_led_working_mode working_mode)
{
    this->pin_num = pin_num;
    this->mode = mode;
    this->working_mode = working_mode;
    rt_pin_mode(pin_num, PIN_MODE_OUTPUT);

    mail = rt_mb_create(("<" + to_string(pin_num) + ">" + " b_l").c_str(), 20, RT_IPC_FLAG_PRIO);
    if (!mail)
    {
        LOG_E("error:beep pin <%d> create mail fail", pin_num);
        goto end;
    }

    if (mode == beep_led_active_LOW)
        rt_pin_write(pin_num, PIN_HIGH);
    else
        rt_pin_write(pin_num, PIN_LOW);

    LOG_I("beep_led at pin <%d> create ok", pin_num);
    init_flag = beep_led_status_ok;
    return;
    end:
    LOG_E("beep_led at pin <%d> create fail", pin_num);
    init_flag = beep_led_status_fail;
    return;
}

BEEP_LED::~BEEP_LED()
{
    if (mail) rt_mb_delete(mail);
}
void BEEP_LED::BEEP_LED_in_thread()
{
    Pbeep_led_mail temp = nullptr;
    beep_led_mail temp_c = { .times = 0,.active_time = 5000, .idle_time = 5000 };
    uint32_t i;
    if (init_flag != beep_led_status_ok) while (1)
    {
        LOG_W("beep_led create not ok!");
        rt_thread_mdelay(1000);
    }

    while (1)
    {

        switch (working_mode)
        {
        case beep_led_working_mode_brust:
            if (rt_mb_recv(mail, (rt_uint32_t*) &temp, RT_WAITING_FOREVER) == RT_EOK)
            {
                for (i = 0; i < temp->times; i++)
                {
                    if (mode == beep_led_active_LOW)
                    {
                        rt_pin_write(pin_num, PIN_LOW);
                        rt_thread_mdelay(temp->active_time);
                        rt_pin_write(pin_num, PIN_HIGH);
                        rt_thread_mdelay(temp->idle_time);
                    }
                    else
                    {
                        rt_pin_write(pin_num, PIN_HIGH);
                        rt_thread_mdelay(temp->active_time);
                        rt_pin_write(pin_num, PIN_LOW);
                        rt_thread_mdelay(temp->idle_time);
                    }
                }
            }
            break;

        case beep_led_working_mode_continue:
            if (rt_mb_recv(mail, (rt_uint32_t*) &temp, RT_WAITING_NO) == RT_EOK)
            {
                temp_c.active_time = temp->active_time;
                temp_c.idle_time = temp->idle_time;
            }
            if (mode == beep_led_active_LOW)
            {
                rt_pin_write(pin_num, PIN_LOW);
                rt_thread_mdelay(temp_c.active_time);
                rt_pin_write(pin_num, PIN_HIGH);
                rt_thread_mdelay(temp_c.idle_time);
            }
            else
            {
                rt_pin_write(pin_num, PIN_HIGH);
                rt_thread_mdelay(temp_c.active_time);
                rt_pin_write(pin_num, PIN_LOW);
                rt_thread_mdelay(temp_c.idle_time);
            }

            break;
        default:
            break;
        }
        if (temp)
        {
            delete (temp);
            temp = nullptr;
        }

    }
}

beep_led_status BEEP_LED::BEEP_LED_send_beep(uint32_t times, uint32_t active_time, uint32_t idle_time) // 次数 活跃时间 idle时间
{
    Pbeep_led_mail temp = nullptr;
    if (init_flag != beep_led_status_ok) goto end;

    temp = new beep_led_mail;
    if (!temp)
    {
        LOG_E("beep_led mail create fail!");
        goto end;
    }

    temp->active_time = active_time;
    temp->idle_time = idle_time;
    temp->times = times;

    if (rt_mb_send(mail, (rt_uint32_t) temp) != RT_EOK)
    {
        LOG_E("beep_led at pin <%d> send mail fail", pin_num);
        goto end;
    }

    return beep_led_status_ok;
    end: if (temp) delete (temp);
    return beep_led_status_fail;
}

beep_led_status BEEP_LED::BEEP_LED_read_init_status()
{
    return init_flag;
}

